home *** CD-ROM | disk | FTP | other *** search
/ Software of the Month Club 2000 October / Software of the Month - Ultimate Collection Shareware 277.iso / pc / PROGRAMS / UTILITY / WINLINUX / DATA1.CAB / programs_-_include / ASM-SPAR.{_A / UACCESS.H < prev    next >
C/C++ Source or Header  |  1999-09-17  |  12KB  |  371 lines

  1. /* $Id: uaccess.h,v 1.28 1998/10/11 06:58:34 davem Exp $ */
  2. #ifndef _ASM_UACCESS_H
  3. #define _ASM_UACCESS_H
  4.  
  5. /*
  6.  * User space memory access functions
  7.  */
  8.  
  9. #ifdef __KERNEL__
  10. #include <linux/sched.h>
  11. #include <linux/string.h>
  12. #include <asm/a.out.h>
  13. #include <asm/asi.h>
  14. #include <asm/system.h>
  15. #include <asm/spitfire.h>
  16. #endif
  17.  
  18. #ifndef __ASSEMBLY__
  19.  
  20. /*
  21.  * Sparc64 is segmented, though more like the M68K than the I386. 
  22.  * We use the secondary ASI to address user memory, which references a
  23.  * completely different VM map, thus there is zero chance of the user
  24.  * doing something queer and tricking us into poking kernel memory.
  25.  *
  26.  * What is left here is basically what is needed for the other parts of
  27.  * the kernel that expect to be able to manipulate, erum, "segments".
  28.  * Or perhaps more properly, permissions.
  29.  *
  30.  * "For historical reasons, these macros are grossly misnamed." -Linus
  31.  */
  32.  
  33. #define KERNEL_DS   ((mm_segment_t) { 0x00 })
  34. #define USER_DS     ((mm_segment_t) { 0x2B })    /* har har har */
  35.  
  36. #define VERIFY_READ    0
  37. #define VERIFY_WRITE    1
  38.  
  39. #define get_fs() (current->tss.current_ds)
  40. #define get_ds() (KERNEL_DS)
  41.  
  42. #define segment_eq(a,b)  ((a).seg == (b).seg)
  43.  
  44. extern spinlock_t scheduler_lock;
  45.  
  46. #define set_fs(val)                                \
  47. do {                                        \
  48.     if (current->tss.current_ds.seg != val.seg) {                \
  49.         spin_lock(&scheduler_lock);                    \
  50.         current->tss.current_ds = (val);                \
  51.         if (segment_eq((val), KERNEL_DS)) {                \
  52.             flushw_user ();                        \
  53.             current->tss.ctx = 0;                    \
  54.         } else {                            \
  55.             current->tss.ctx = (current->mm->context & 0x3ff);    \
  56.         }                                \
  57.         spitfire_set_secondary_context(current->tss.ctx);         \
  58.         __asm__ __volatile__("flush %g6");                \
  59.         spin_unlock(&scheduler_lock);                    \
  60.     }                                    \
  61. } while(0)
  62.  
  63. #define __user_ok(addr,size) 1
  64. #define __kernel_ok (segment_eq(get_fs(), KERNEL_DS))
  65. #define __access_ok(addr,size) 1
  66. #define access_ok(type,addr,size) 1
  67.  
  68. extern inline int verify_area(int type, const void * addr, unsigned long size)
  69. {
  70.     return 0;
  71. }
  72.  
  73. /*
  74.  * The exception table consists of pairs of addresses: the first is the
  75.  * address of an instruction that is allowed to fault, and the second is
  76.  * the address at which the program should continue.  No registers are
  77.  * modified, so it is entirely up to the continuation code to figure out
  78.  * what to do.
  79.  *
  80.  * All the routines below use bits of fixup code that are out of line
  81.  * with the main instruction path.  This means when everything is well,
  82.  * we don't even have to jump over them.  Further, they do not intrude
  83.  * on our cache or tlb entries.
  84.  *
  85.  * There is a special way how to put a range of potentially faulting
  86.  * insns (like twenty ldd/std's with now intervening other instructions)
  87.  * You specify address of first in insn and 0 in fixup and in the next
  88.  * exception_table_entry you specify last potentially faulting insn + 1
  89.  * and in fixup the routine which should handle the fault.
  90.  * That fixup code will get
  91.  * (faulting_insn_address - first_insn_in_the_range_address)/4
  92.  * in %g2 (ie. index of the faulting instruction in the range).
  93.  */
  94.  
  95. struct exception_table_entry
  96. {
  97.         unsigned insn, fixup;
  98. };
  99.  
  100. /* Returns 0 if exception not found and fixup otherwise.  */
  101. extern unsigned long search_exception_table(unsigned long, unsigned long *);
  102.  
  103. extern void __ret_efault(void);
  104.  
  105. /* Uh, these should become the main single-value transfer routines..
  106.  * They automatically use the right size if we just have the right
  107.  * pointer type..
  108.  *
  109.  * This gets kind of ugly. We want to return _two_ values in "get_user()"
  110.  * and yet we don't want to do any pointers, because that is too much
  111.  * of a performance impact. Thus we have a few rather ugly macros here,
  112.  * and hide all the uglyness from the user.
  113.  */
  114. #define put_user(x,ptr) ({ \
  115. unsigned long __pu_addr = (unsigned long)(ptr); \
  116. __put_user_nocheck((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr))); })
  117.  
  118. #define put_user_ret(x,ptr,retval) ({ \
  119. unsigned long __pu_addr = (unsigned long)(ptr); \
  120. __put_user_nocheck_ret((__typeof__(*(ptr)))(x),__pu_addr,sizeof(*(ptr)),retval); })
  121.  
  122. #define get_user(x,ptr) ({ \
  123. unsigned long __gu_addr = (unsigned long)(ptr); \
  124. __get_user_nocheck((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr))); })
  125.  
  126. #define get_user_ret(x,ptr,retval) ({ \
  127. unsigned long __gu_addr = (unsigned long)(ptr); \
  128. __get_user_nocheck_ret((x),__gu_addr,sizeof(*(ptr)),__typeof__(*(ptr)),retval); })
  129.  
  130. #define __put_user(x,ptr) put_user(x,ptr)
  131. #define __put_user_ret(x,ptr,retval) put_user_ret(x,ptr,retval)
  132. #define __get_user(x,ptr) get_user(x,ptr)
  133. #define __get_user_ret(x,ptr,retval) get_user_ret(x,ptr,retval)
  134.  
  135. struct __large_struct { unsigned long buf[100]; };
  136. #define __m(x) ((struct __large_struct *)(x))
  137.  
  138. #define __put_user_nocheck(data,addr,size) ({ \
  139. register int __pu_ret; \
  140. switch (size) { \
  141. case 1: __put_user_asm(data,b,addr,__pu_ret); break; \
  142. case 2: __put_user_asm(data,h,addr,__pu_ret); break; \
  143. case 4: __put_user_asm(data,w,addr,__pu_ret); break; \
  144. case 8: __put_user_asm(data,x,addr,__pu_ret); break; \
  145. default: __pu_ret = __put_user_bad(); break; \
  146. } __pu_ret; })
  147.  
  148. #define __put_user_nocheck_ret(data,addr,size,retval) ({ \
  149. register int __foo __asm__ ("l1"); \
  150. switch (size) { \
  151. case 1: __put_user_asm_ret(data,b,addr,retval,__foo); break; \
  152. case 2: __put_user_asm_ret(data,h,addr,retval,__foo); break; \
  153. case 4: __put_user_asm_ret(data,w,addr,retval,__foo); break; \
  154. case 8: __put_user_asm_ret(data,x,addr,retval,__foo); break; \
  155. default: if (__put_user_bad()) return retval; break; \
  156. } })
  157.  
  158. #define __put_user_asm(x,size,addr,ret)                    \
  159. __asm__ __volatile__(                            \
  160.     "/* Put user asm, inline. */\n"                    \
  161. "1:\t"    "st"#size "a %1, [%2] %4\n\t"                    \
  162.     "clr    %0\n"                            \
  163. "2:\n\n\t"                                \
  164.     ".section .fixup,#alloc,#execinstr\n\t"                \
  165.     ".align    4\n"                            \
  166. "3:\n\t"                                \
  167.     "b    2b\n\t"                            \
  168.     " mov    %3, %0\n\n\t"                        \
  169.     ".previous\n\t"                            \
  170.     ".section __ex_table,#alloc\n\t"                \
  171.     ".align    4\n\t"                            \
  172.     ".word    1b, 3b\n\t"                        \
  173.     ".previous\n\n\t"                        \
  174.        : "=r" (ret) : "r" (x), "r" (__m(addr)),                \
  175.      "i" (-EFAULT), "i" (ASI_S))
  176.  
  177. #define __put_user_asm_ret(x,size,addr,ret,foo)                \
  178. if (__builtin_constant_p(ret) && ret == -EFAULT)            \
  179. __asm__ __volatile__(                            \
  180.     "/* Put user asm ret, inline. */\n"                \
  181. "1:\t"    "st"#size "a %1, [%2] %3\n\n\t"                    \
  182.     ".section __ex_table,#alloc\n\t"                \
  183.     ".align    4\n\t"                            \
  184.     ".word    1b, __ret_efault\n\n\t"                    \
  185.     ".previous\n\n\t"                        \
  186.        : "=r" (foo) : "r" (x), "r" (__m(addr)), "i" (ASI_S));        \
  187. else                                    \
  188. __asm__ __volatile(                            \
  189.     "/* Put user asm ret, inline. */\n"                \
  190. "1:\t"    "st"#size "a %1, [%2] %4\n\n\t"                    \
  191.     ".section .fixup,#alloc,#execinstr\n\t"                \
  192.     ".align    4\n"                            \
  193. "3:\n\t"                                \
  194.     "ret\n\t"                            \
  195.     " restore %%g0, %3, %%o0\n\n\t"                    \
  196.     ".previous\n\t"                            \
  197.     ".section __ex_table,#alloc\n\t"                \
  198.     ".align    4\n\t"                            \
  199.     ".word    1b, 3b\n\n\t"                        \
  200.     ".previous\n\n\t"                        \
  201.        : "=r" (foo) : "r" (x), "r" (__m(addr)),                \
  202.          "i" (ret), "i" (ASI_S))
  203.  
  204. extern int __put_user_bad(void);
  205.  
  206. #define __get_user_nocheck(data,addr,size,type) ({ \
  207. register int __gu_ret; \
  208. register unsigned long __gu_val; \
  209. switch (size) { \
  210. case 1: __get_user_asm(__gu_val,ub,addr,__gu_ret); break; \
  211. case 2: __get_user_asm(__gu_val,uh,addr,__gu_ret); break; \
  212. case 4: __get_user_asm(__gu_val,uw,addr,__gu_ret); break; \
  213. case 8: __get_user_asm(__gu_val,x,addr,__gu_ret); break; \
  214. default: __gu_val = 0; __gu_ret = __get_user_bad(); break; \
  215. } data = (type) __gu_val; __gu_ret; })
  216.  
  217. #define __get_user_nocheck_ret(data,addr,size,type,retval) ({ \
  218. register unsigned long __gu_val __asm__ ("l1"); \
  219. switch (size) { \
  220. case 1: __get_user_asm_ret(__gu_val,ub,addr,retval); break; \
  221. case 2: __get_user_asm_ret(__gu_val,uh,addr,retval); break; \
  222. case 4: __get_user_asm_ret(__gu_val,uw,addr,retval); break; \
  223. case 8: __get_user_asm_ret(__gu_val,x,addr,retval); break; \
  224. default: if (__get_user_bad()) return retval; \
  225. } data = (type) __gu_val; })
  226.  
  227. #define __get_user_asm(x,size,addr,ret)                    \
  228. __asm__ __volatile__(                            \
  229.     "/* Get user asm, inline. */\n"                    \
  230. "1:\t"    "ld"#size "a [%2] %4, %1\n\t"                    \
  231.     "clr    %0\n"                            \
  232. "2:\n\n\t"                                \
  233.     ".section .fixup,#alloc,#execinstr\n\t"                \
  234.     ".align    4\n"                            \
  235. "3:\n\t"                                \
  236.     "clr    %1\n\t"                            \
  237.     "b    2b\n\t"                            \
  238.     " mov    %3, %0\n\n\t"                        \
  239.     ".previous\n\t"                            \
  240.     ".section __ex_table,#alloc\n\t"                \
  241.     ".align    4\n\t"                            \
  242.     ".word    1b, 3b\n\n\t"                        \
  243.     ".previous\n\t"                            \
  244.        : "=r" (ret), "=r" (x) : "r" (__m(addr)),            \
  245.      "i" (-EFAULT), "i" (ASI_S))
  246.  
  247. #define __get_user_asm_ret(x,size,addr,retval)                \
  248. if (__builtin_constant_p(retval) && retval == -EFAULT)            \
  249. __asm__ __volatile__(                            \
  250.     "/* Get user asm ret, inline. */\n"                \
  251. "1:\t"    "ld"#size "a [%1] %2, %0\n\n\t"                    \
  252.     ".section __ex_table,#alloc\n\t"                \
  253.     ".align    4\n\t"                            \
  254.     ".word    1b,__ret_efault\n\n\t"                    \
  255.     ".previous\n\t"                            \
  256.        : "=r" (x) : "r" (__m(addr)), "i" (ASI_S));            \
  257. else                                    \
  258. __asm__ __volatile__(                            \
  259.     "/* Get user asm ret, inline. */\n"                \
  260. "1:\t"    "ld"#size "a [%1] %2, %0\n\n\t"                    \
  261.     ".section .fixup,#alloc,#execinstr\n\t"                \
  262.     ".align    4\n"                            \
  263. "3:\n\t"                                \
  264.     "ret\n\t"                            \
  265.     " restore %%g0, %3, %%o0\n\n\t"                    \
  266.     ".previous\n\t"                            \
  267.     ".section __ex_table,#alloc\n\t"                \
  268.     ".align    4\n\t"                            \
  269.     ".word    1b, 3b\n\n\t"                        \
  270.     ".previous\n\t"                            \
  271.        : "=r" (x) : "r" (__m(addr)), "i" (retval), "i" (ASI_S))
  272.  
  273. extern int __get_user_bad(void);
  274.  
  275. extern __kernel_size_t __memcpy_short(void *to, const void *from,
  276.                       __kernel_size_t size,
  277.                       long asi_src, long asi_dst);
  278.  
  279. extern __kernel_size_t __memcpy_entry(void *to, const void *from,
  280.                       __kernel_size_t size,
  281.                       long asi_src, long asi_dst);
  282.  
  283. extern __kernel_size_t __memcpy_16plus(void *to, const void *from,
  284.                        __kernel_size_t size,
  285.                        long asi_src, long asi_dst);
  286.  
  287. extern __kernel_size_t __memcpy_386plus(void *to, const void *from,
  288.                     __kernel_size_t size,
  289.                     long asi_src, long asi_dst);
  290.  
  291. extern __kernel_size_t __copy_from_user(void *to, const void *from,
  292.                     __kernel_size_t size);
  293.  
  294. extern __kernel_size_t __copy_to_user(void *to, const void *from,
  295.                       __kernel_size_t size);
  296.  
  297. extern __kernel_size_t __copy_in_user(void *to, const void *from,
  298.                       __kernel_size_t size);
  299.  
  300. #define copy_from_user(to,from,n)        \
  301.     __copy_from_user((void *)(to),    \
  302.             (void *)(from), (__kernel_size_t)(n))
  303.  
  304. #define copy_from_user_ret(to,from,n,retval) ({ \
  305. if (copy_from_user(to,from,n)) \
  306.     return retval; \
  307. })
  308.  
  309. #define __copy_from_user_ret(to,from,n,retval) ({ \
  310. if (__copy_from_user(to,from,n)) \
  311.     return retval; \
  312. })
  313.  
  314. #define copy_to_user(to,from,n) \
  315.     __copy_to_user((void *)(to), \
  316.     (void *) (from), (__kernel_size_t)(n))
  317.  
  318. #define copy_to_user_ret(to,from,n,retval) ({ \
  319. if (copy_to_user(to,from,n)) \
  320.     return retval; \
  321. })
  322.  
  323. #define __copy_to_user_ret(to,from,n,retval) ({ \
  324. if (__copy_to_user(to,from,n)) \
  325.     return retval; \
  326. })
  327.  
  328. #define copy_in_user(to,from,n) \
  329.     __copy_in_user((void *)(to), \
  330.     (void *) (from), (__kernel_size_t)(n))
  331.  
  332. #define copy_in_user_ret(to,from,n,retval) ({ \
  333. if (copy_in_user(to,from,n)) \
  334.     return retval; \
  335. })
  336.  
  337. #define __copy_in_user_ret(to,from,n,retval) ({ \
  338. if (__copy_in_user(to,from,n)) \
  339.     return retval; \
  340. })
  341.  
  342. extern __inline__ __kernel_size_t __clear_user(void *addr, __kernel_size_t size)
  343. {
  344.     extern __kernel_size_t __bzero_noasi(void *addr, __kernel_size_t size);
  345.     
  346.     
  347.     __asm__ __volatile__ ("wr %%g0, %0, %%asi" : : "i" (ASI_S));
  348.     return __bzero_noasi(addr, size);
  349. }
  350.  
  351. #define clear_user(addr,n) \
  352.     __clear_user((void *)(addr), (__kernel_size_t)(n))
  353.  
  354. #define clear_user_ret(addr,size,retval) ({ \
  355. if (clear_user(addr,size)) \
  356.     return retval; \
  357. })
  358.  
  359. extern int __strncpy_from_user(unsigned long dest, unsigned long src, int count);
  360.  
  361. #define strncpy_from_user(dest,src,count) \
  362.     __strncpy_from_user((unsigned long)(dest), (unsigned long)(src), (int)(count))
  363.  
  364. extern int __strlen_user(const char *);
  365.  
  366. #define strlen_user __strlen_user
  367.  
  368. #endif  /* __ASSEMBLY__ */
  369.  
  370. #endif /* _ASM_UACCESS_H */
  371.